package com.piece.core.framework.config;

import com.piece.core.framework.properties.AsyncProperties;
import com.piece.core.framework.util.async.DefaultThreadPoolTaskExecutor;
import com.piece.core.framework.util.basic.SpringUtil;
import com.piece.core.framework.util.cache.Cache;
import com.piece.core.framework.util.cache.CacheFactory;
import com.piece.core.framework.util.message.Message;
import com.piece.core.framework.util.message.MessageFactory;
import com.piece.core.framework.util.message.MessageOperator;
import com.piece.core.framework.util.schedule.ScheduleFactory;
import com.piece.core.framework.util.schedule.ScheduleService;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.context.annotation.Bean;
import org.springframework.core.annotation.Order;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import java.util.Map;
import java.util.concurrent.ThreadPoolExecutor;

@Order(Integer.MIN_VALUE)
@EnableAsync(proxyTargetClass = true)
@ConditionalOnBean(AsyncProperties.class)
public class FrameWorkAutoConfiguration {

    @Bean
    public static ThreadPoolTaskExecutor taskExecutor(AsyncProperties asyncProperties) {
        ThreadPoolTaskExecutor executor = new DefaultThreadPoolTaskExecutor();
        executor.setCorePoolSize(asyncProperties.getCorePoolSize());
        executor.setMaxPoolSize(asyncProperties.getMaxPoolSize());
        executor.setQueueCapacity(asyncProperties.getQueueCapacity());
        executor.setThreadNamePrefix(asyncProperties.getThreadNamePrefix());
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        executor.initialize();
        return executor;
    }

    @Bean
    public static SpringUtil springUtil() {
        return new SpringUtil();
    }

    @Bean
    public CacheFactory cacheFactory(Map<String, Cache> cacheMap) {
        return new CacheFactory(cacheMap);
    }

    @Bean
    public MessageFactory messageFactory(Map<String, Message> messageMap, Map<String, MessageOperator> messageOperatorMap) {
        return new MessageFactory(messageMap, messageOperatorMap);
    }

    @Bean
    public ScheduleFactory scheduleFactory(Map<String, ScheduleService> scheduleServiceMap) {
        return new ScheduleFactory(scheduleServiceMap);
    }
}
